package com.hcms.admin.aop;

import com.hcms.admin.annotation.CheckPermission;
import com.hcms.admin.service.ISysAdminService;
import com.hcms.common.exception.ApiException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;

@Aspect
@Component
public class CheckPermissionAop {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private ISysAdminService sysAdminService;

    @Pointcut("execution(* com.hcms.admin.controller..*(..))")
    public void check() {
    }

//    @Before("check()")
//    public void doBeforeCheck() {
//        logger.info("Run doBeforeCheck()");
//    }

//    @After("check()")
//    public void doAfterCheck() {
//        logger.info("Run doAfterCheck()");
//    }

    /**
     * 默认所有接口都要校验权限，除非关闭权限校验
     *
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("check()")
    public Object doAroundCheck(ProceedingJoinPoint joinPoint) throws Throwable {
        logger.info("Run doAroundCheck()");
        Object target = joinPoint.getTarget();
        String simpleName = target.getClass().getSimpleName();
        String methodName = joinPoint.getSignature().getName();
        String permName = simpleName.substring(0, 1).toLowerCase() + simpleName.substring(1, simpleName.lastIndexOf("Controller")) + ":" + methodName;
        String[] basePerm = {permName};
        logger.info("Permission Name: {}", permName);
        Method[] methods = target.getClass().getMethods();
        boolean hasPerm = true;
        for (Method method : methods) {
            if (method.getName().equals(methodName)) {
                CheckPermission annotation = method.getAnnotation(CheckPermission.class);
                if (annotation != null) {
                    String[] value = annotation.value();
                    //检查接口是否需要校验权限
                    if (annotation.check()) {
                        hasPerm = sysAdminService.checkPermissions(value.length > 0 ? value : basePerm);
                    }
                } else {
                    hasPerm = sysAdminService.checkPermissions(basePerm);
                }
            }
        }
        if (hasPerm) {
            logger.info("User has permission");
            return joinPoint.proceed();
        } else {
            logger.error("The user has no operation permission");
            throw new ApiException("无操作权限");
        }
    }
}
